package com.yupi.yurpc.serializer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * @program: yu-rpc
 * @description: Java Lotus
 * @author: spring
 * @create: 2024-10-23
 * Jdk的序列化
 */
public class JdkSerializer implements Serializer {

    /**
     * 序列化
     *
     * @param object 对象
     * @param <T>    泛型
     * @return 序列化成为字节数组
     * @throws IOException 抛出异常
     */
    /*
    这段代码是一个通用的序列化方法，用于将一个对象转换为字节数组。它使用ByteArrayOutputStream作为输出流，配合ObjectOutputStream来写入对象。具体步骤如下：
    创建ByteArrayOutputStream实例以存储序列化的字节。
    创建ObjectOutputStream，将其与ByteArrayOutputStream关联。
    调用writeObject方法将传入的对象序列化到输出流。
    关闭ObjectOutputStream，确保所有数据被写入。
    返回生成的字节数组。
    此方法在处理序列化时会抛出IOException，所以需要声明异常。
     */
    @Override
    public <T> byte[] serializer(T object) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(object);
        objectOutputStream.close();
        return outputStream.toByteArray();
    }


    /**
     * 反序列化
     *
     * @param bytes 字节数组
     * @param type  类型
     * @param <T>   泛型
     * @return 返回对象
     * @throws IOException 抛出异常
     */
    /*
    这段代码是一个通用的反序列化方法，用于将字节数组转换为指定类型的对象。其工作流程如下：
    创建ByteArrayInputStream实例，读取传入的字节数组。
    使用ObjectInputStream关联输入流，准备反序列化。
    调用readObject方法读取对象，并强制转换为指定类型T。
    如果出现ClassNotFoundException，则抛出运行时异常。
    最后，在finally块中关闭ObjectInputStream，以释放资源。
    该方法同样会抛出IOException。
     */
    @Override
    public <T> T deserializer(byte[] bytes, Class<T> type) throws IOException {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        try {
            return (T) objectInputStream.readObject();
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            objectInputStream.close();
        }
    }
}
